home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 26 / Mac Magazin and MacEasy Magazine CD - Issue 26.iso / Wissenschaft & Technik / Mercutio_v1.3f / Sample Codeƒ / PopupDialog.p < prev    next >
Text File  |  1996-08-20  |  12KB  |  385 lines

  1. UNIT PopupDialog;
  2. INTERFACE
  3.     USES
  4. {$IFC UNDEFINED THINK_PASCAL}
  5. {$SETC THINK_PASCAL=FALSE}
  6. {$ENDC}
  7. {$IFC THINK_PASCAL=FALSE}
  8.         Types, ToolUtils, Resources, Controls, Menus, Memory, QuickDraw, QuickDrawText, OSUtils, Events, Dialogs, Windows, Fonts, 
  9. {$ENDC}
  10.         LowMem, MercutioAPI;
  11.     CONST
  12.         Off = 0;
  13.         On = 1;
  14.         Disable = 255;
  15.  
  16.         enterKey = 3;
  17.         helpKey = 5;
  18.         deleteKey = 8;
  19.         tabKey = 9;
  20.         linefeedKey = 10;
  21.         CR = 13;
  22.  
  23.         periodKey = 46;
  24.         slashKey = 47;
  25.         questionmarkKey = 63;
  26.  
  27.         PopupDLOG = 3001;
  28.         popup1Item = 3;
  29.         popup2Item = 7;
  30.         defaultItem = 5;
  31.     
  32.         normalPopupID = 11;
  33.         smallPopupID = 12;
  34.         
  35.     PROCEDURE doPopupDialog;
  36.  
  37. IMPLEMENTATION
  38.  
  39.     TYPE
  40.         popupInfo = RECORD
  41.             hMenu: MenuHandle;
  42.             selectedItem: integer;
  43.             smallFont : Boolean;
  44.         END;
  45.         DialogGlobals = RECORD
  46.                 menus : array [normalPopupID..smallPopupID] of popupInfo;
  47.             END;
  48.         DialogGlobalsPtr = ^DialogGlobals;
  49.  
  50.     FUNCTION ItemToMenuID(item:integer):integer;
  51.     BEGIN
  52.         IF item = popup1Item THEN ItemToMenuID:= normalPopupID ELSE ItemToMenuID := smallPopupID; 
  53.     END;
  54.     
  55.     PROCEDURE FakeClick (VAR theDialog: DialogPtr; theButton: Integer);
  56. { select/deselect a button in a Dialog }
  57.         VAR
  58.             theType: Integer;
  59.             itemHandle: Handle;
  60.             iRect: Rect;
  61.             Ticks: LongInt;
  62.     BEGIN
  63.         GetDialogItem(theDialog, theButton, theType, itemHandle, iRect);
  64.         HiliteControl(ControlHandle(itemHandle), On);
  65.         Delay(8, Ticks);
  66.         HiliteControl(ControlHandle(itemHandle), Off);
  67.     END; { of proc FakeClick }
  68.  
  69.     PROCEDURE DrawDefaultBtn (theDialog: DialogPtr; ItemNumber: Integer);
  70.   { heavy black outline }
  71.         VAR
  72.             iType: Integer;
  73.             itemHdl: Handle;
  74.             ps: PenState;
  75.             iRect: Rect;
  76.     BEGIN
  77.         SetPort(theDialog);                 { set window to current graf port }
  78.         GetDialogItem(theDialog, ItemNumber, iType, itemHdl, iRect); { get location }
  79.         GetPenState(ps);                               { save current pen }
  80.         PenNormal;
  81.         PenSize(3, 3);
  82.         InsetRect(iRect, -4, -4);
  83.         FrameRoundRect(iRect, 16, 16);
  84.         SetPenState(ps);                               { restore old pen }
  85.     END;  { of proc DrawDefaultBtn }
  86.  
  87.  
  88.     PROCEDURE UpdatePopUp (theDialog: DialogPtr; Item: Integer);
  89. {   draw popup menu }
  90.         VAR
  91.             aRect: Rect;
  92.             theGlobals: DialogGlobalsPtr;
  93.             IsNovice: boolean;
  94.             theType: Integer;
  95.             itemHdl: Handle;
  96.             iRect: Rect;
  97.             menuID:integer;
  98.     BEGIN
  99.         theGlobals := DialogGlobalsPtr(GetWRefCon(theDialog));
  100.         menuID := ItemToMenuID(Item);
  101.         GetDialogItem(theDialog, Item, theType, itemHdl, aRect);
  102.         InsetRect(aRect, -2, -2);
  103.         EraseRect(aRect);
  104.         InsetRect(aRect, 2, 2);
  105.  
  106.         IF theGlobals^.menus[menuID].smallFont THEN BEGIN
  107.             TextSize(9);
  108.             TextFont(geneva);
  109.             END;
  110.         MDEF_CalcItemSize(theGlobals^.menus[menuID].hMenu, theGlobals^.menus[menuID].selectedItem, aRect);
  111.  
  112.         MoveTo(aRect.left + 2, aRect.bottom);
  113.         LineTo(aRect.right, aRect.bottom);
  114.         MoveTo(aRect.right, aRect.top + 2);
  115.         LineTo(aRect.right, aRect.bottom);
  116.  
  117.         MoveTo(aRect.left + 6, aRect.bottom - 5);    { move to text position }
  118.         FillRect(aRect, qd.white);
  119.  
  120.         MDEF_DrawItem(theGlobals^.menus[menuID].hMenu, theGlobals^.menus[menuID].selectedItem, aRect);
  121.  
  122.         FrameRect(aRect);
  123.         SetDialogItem(theDialog, Item, theType, itemHdl, aRect);
  124.         IF theGlobals^.menus[menuID].smallFont THEN BEGIN
  125.             TextSize(0);
  126.             TextFont(0);
  127.             END;
  128.     END;
  129.  
  130.  
  131.     FUNCTION PopUpSelectWithWindowFont (theMenu : MenuHandle; popPt: Point; popupItem: integer; useWFont: boolean): integer;
  132.     VAR
  133.         item: integer;
  134.         itemMark : char;
  135.         oldSysFont, oldWMgrFont, oldCWMgrFont: integer;
  136.         oldSysSize, oldWMgrSize, oldCWMgrSize: integer;
  137.         saveFontFam: integer;
  138.         curPort: GrafPtr;
  139.         wMgrPort: GrafPtr;
  140.         wMgrCPort: CGrafPtr;
  141.         theWorld:SysEnvRec;
  142.     BEGIN
  143.         oldSysFont := LMGetSysFontFam;
  144.         oldSysSize := LMGetSysFontSize;
  145.         GetPort(curPort);
  146.         IF ((curPort^.txFont = oldSysFont) & (curPort^.txSize = oldSysSize)) THEN
  147.             useWFont := false;
  148.             
  149.         IF useWFont THEN BEGIN
  150.             { hack to fix bugs caused by programs that mess up the WindowMgr port(s)
  151.               (e.g. MacWrite & Word)  - thanks to Leonard Rosenthal for soln }
  152.             GetWMgrPort(wMgrPort);
  153.             SetPort(wMgrPort);
  154.             oldWMgrFont := wMgrPort^.txFont;
  155.             oldWMgrSize := wMgrPort^.txSize;
  156.             TextFont(wMgrPort^.txFont);
  157.             TextSize(wMgrPort^.txSize);
  158.             IF ((SysEnvirons (1, theWorld) = noErr) & (theWorld.hasColorQD)) THEN BEGIN
  159.                 GetCWMgrPort(wMgrCPort);
  160.                 SetPort(GrafPtr(wMgrCPort));
  161.                 oldCWMgrFont := wMgrCPort^.txFont;
  162.                 oldCWMgrSize := wMgrCPort^.txSize;
  163.                 TextFont(wMgrCPort^.txFont);
  164.                 TextSize(wMgrCPort^.txSize);
  165.                 END
  166.             ELSE
  167.                 theWorld.hasColorQD:=false;
  168.             { end-of-hack }
  169.             
  170.             SetPort(curPort);
  171.             
  172.             LMSetSysFontFam(curPort^.txFont);
  173.             LMSetSysFontSize(curPort^.txSize);
  174.             LMSetLastSPExtra(longint(-1));
  175.             END;
  176.         
  177.         IF (popupItem > 0) THEN BEGIN
  178.             GetItemMark(theMenu, popupItem, itemMark);
  179.             IF useWFont THEN
  180.                 SetItemMark(theMenu, popupItem, '*')
  181.             ELSE
  182.                 SetItemMark(theMenu, popupItem, char(checkMark));
  183.         END;
  184.         
  185.         CalcMenuSize(theMenu);
  186.         item := PopUpMenuSelect(theMenu, popPt.v, popPt.h, popupItem);
  187.         
  188.         IF (popupItem > 0) THEN
  189.             SetItemMark(theMenu, popupItem, itemMark);
  190.             
  191.         IF useWFont THEN BEGIN
  192.             { part 2 of hack }
  193.             SetPort(wMgrPort);
  194.             TextFont(oldWMgrFont);
  195.             TextSize(oldWMgrFont);
  196.             IF theWorld.hasColorQD THEN BEGIN
  197.                 SetPort(GrafPtr(wMgrCPort));
  198.                 TextFont(oldCWMgrFont);
  199.                 TextSize(oldCWMgrSize);
  200.             END;
  201.             { end-of-hack-part-2 }
  202.  
  203.             SetPort(curPort);
  204.             
  205.             LMSetSysFontSize(oldSysSize);
  206.             LMSetSysFontFam(oldSysFont);
  207.             LMSetLastSPExtra(longint(-1));
  208.             END;
  209.             
  210.         PopUpSelectWithWindowFont := item;
  211.     END;
  212.  
  213.     PROCEDURE HandleMouseDown (theDialog:DialogPtr; itemHit: integer);
  214.         VAR
  215.             theGlobals: DialogGlobalsPtr;
  216.             iType: integer;
  217.             iRect: Rect;
  218.             iHandle: Handle;
  219.             popupRect: Rect;
  220.             popupResult:integer;
  221.             menuID:integer;
  222.         BEGIN
  223.             theGlobals := DialogGlobalsPtr(GetWRefCon(theDialog));
  224.             menuID := ItemToMenuID(itemHit);
  225.             CASE itemHit OF
  226.                 popup1Item, popup2Item:  BEGIN
  227.                         GetDialogItem(theDialog, itemHit, iType, iHandle, iRect);
  228.                         SetRect(popupRect, iRect.left , iRect.top, iRect.left + theGlobals^.menus[menuID].hMenu^^.menuWidth + 4, iRect.bottom + 2);
  229.                         LocalToGlobal(popupRect.topLeft);
  230.                         LocalToGlobal(popupRect.botRight);
  231.                         InsetRect(iRect, 1, 1);
  232.                         {InvertRect(iRect);}
  233.  
  234.                         IF theGlobals^.menus[menuID].smallFont THEN BEGIN
  235.                             TextFont(geneva);
  236.                             TextSize(9);
  237.                             END;
  238.                         popupResult := PopUpSelectWithWindowFont(theGlobals^.menus[menuID].hMenu, popupRect.topLeft, theGlobals^.menus[menuID].selectedItem, theGlobals^.menus[menuID].smallFont);
  239.                         IF theGlobals^.menus[menuID].smallFont THEN BEGIN
  240.                             TextSize(0);
  241.                             TextFont(0);
  242.                             END;
  243.  
  244.                         {InvertRect(iRect);}
  245.                         IF (popupResult > 0) AND (LoWord(popupResult) <> theGlobals^.menus[menuID].selectedItem) THEN BEGIN
  246.                                 CheckItem(theGlobals^.menus[menuID].hMenu, theGlobals^.menus[menuID].selectedItem, False);
  247.                                 theGlobals^.menus[menuID].selectedItem := LoWord(popupResult);
  248.                                 UpdatePopUp(theDialog, itemHit);
  249.                             END;
  250.                     END;
  251.                 OTHERWISE
  252.                     ;
  253.             END;
  254.         END;
  255.  
  256.     PROCEDURE HandleEvents (theDialog:DialogPtr);
  257.         VAR
  258.             theGlobals: DialogGlobalsPtr;
  259.             eventOccured: boolean;
  260.             theErr: longint;
  261.             ShiftUsed, CmdKeyUsed, BadKey: boolean;
  262.             itemHit: integer;
  263.             theEvent: EventRecord;
  264.             thePoint: Point;
  265.             theKey: integer;
  266.             whichWindow: WindowPtr;            { Dummy,cause we have no windows}
  267.             windowLoc: integer;
  268.             matchedItem: longint;
  269.             menuNum: Integer;                { Res ID of the menu Selected    }
  270.             itemNum: Integer;                { The item number selected    }
  271.     BEGIN
  272.             theGlobals := DialogGlobalsPtr(GetWRefCon(theDialog));
  273.             REPEAT
  274.                 eventOccured := GetNextEvent(everyEvent, theEvent);
  275.                 IF eventOccured THEN BEGIN
  276.                     IF IsDialogEvent(theEvent) THEN
  277.                         IF  DialogSelect(theEvent, DialogPtr(whichWindow), itemHit) THEN 
  278.                             HandleMouseDown(DialogPtr(whichWindow), itemHit);
  279.                     CASE theEvent.what OF
  280.                         keyDown, autoKey:{ any key down! }
  281.                             BEGIN
  282.                                 theKey := BitAnd(theEvent.message, charCodeMask);        { decode char }
  283.                                 CmdKeyUsed := (BitAnd(theEvent.modifiers, cmdKey) <> 0);    { cmd key down? }
  284.                                 ShiftUsed := (BitAnd(theEvent.modifiers, shiftKey) <> 0);        { shift key down? }
  285.                                 CASE theKey OF
  286.                                     enterKey, CR:    { OK Button equivalents }
  287.                                         BEGIN
  288.                                             itemHit := ok;
  289.                                             FakeClick(theDialog, itemHit);
  290.                                         END;
  291.                                     OTHERWISE
  292.                                         IF CmdKeyUsed & (theKey = periodKey) THEN BEGIN
  293.                                                 FakeClick(theDialog, cancel);
  294.                                                 itemHit := cancel;
  295.                                         END ELSE BEGIN
  296.                                                 matchedItem := MDEF_MenuKey(theEvent.message, theEvent.modifiers, theGlobals^.menus[normalPopupID].hMenu);
  297.                                                 IF (matchedItem > 0) THEN BEGIN 
  298.                                                     menuNum := HiWrd(matchedItem);    { get the menu number        }
  299.                                                     itemNum := LoWrd(matchedItem);    { get the item number        }
  300.                                                     IF menuNum = normalPopupID THEN BEGIN
  301.                                                         theGlobals^.menus[menuNum].selectedItem := itemNum;
  302.                                                         UpdatePopUp(theDialog, 3);
  303.                                                     END ELSE IF menuNum = smallPopupID THEN BEGIN
  304.                                                         theGlobals^.menus[menuNum].selectedItem := itemNum;
  305.                                                         UpdatePopUp(theDialog, 7);
  306.                                                     END;
  307.                                                 END;
  308.                                         END;
  309.                                 END;
  310.                             END;
  311.                         mouseDown:            { we had a mouse-down theEvent    }
  312.                             BEGIN
  313.                                 windowLoc := FindWindow(theEvent.where, whichWindow); { find out where }
  314.                                 CASE windowLoc OF        { now case on the location    }
  315.                                     inMenuBar:  BEGIN
  316.                                             SysBeep(1);
  317.                                         END;
  318.                                     inSysWindow: 
  319.                                         SystemClick(theEvent, whichWindow); {It was in a desk acc    }
  320.                                     inDrag: BEGIN
  321.                                         DragWindow(whichWindow, theEvent.where, GetGrayRgn^^.rgnBBox);
  322.                                         END;
  323.                                     inContent: 
  324.                                         IF FrontWindow <> whichWindow THEN
  325.                                             SelectWindow(whichWindow);
  326.                                     OTHERWISE BEGIN
  327.                                         END;
  328.                                 END;
  329.                             END;
  330.                         OTHERWISE BEGIN
  331.                             IF DialogSelect(theEvent, DialogPtr(whichWindow), itemHit) THEN BEGIN END;
  332.                         END;
  333.                     END;
  334.                 END;
  335.         UNTIL itemHit IN [ok, cancel];
  336.     END;
  337.     
  338.     
  339.     PROCEDURE doPopupDialog;
  340.         VAR
  341.             theDialog: DialogPtr;
  342.             iType: integer;
  343.             iRect: Rect;
  344.             iHandle: Handle;
  345.             popupRect: Rect;
  346.             theGlobals: DialogGlobals;
  347.     BEGIN
  348.         theDialog := GetNewDialog(PopupDLOG, NIL, Pointer(-1));
  349.         IF theDialog = NIL THEN BEGIN
  350.                 SysBeep(1);
  351.                 exit(doPopupDialog);
  352.             END;
  353.         SetPort(theDialog);
  354.         
  355.         SetWRefCon(theDialog, longint(@theGlobals));
  356.  
  357.         theGlobals.menus[normalPopupID].hMenu := GetMenu(normalPopupID);
  358.         InsertMenu(theGlobals.menus[normalPopupID].hMenu, -1);
  359.         CalcMenuSize(theGlobals.menus[normalPopupID].hMenu);
  360.         theGlobals.menus[normalPopupID].selectedItem := 1;
  361.         theGlobals.menus[normalPopupID].smallFont := FALSE;
  362.         GetDialogItem(theDialog, popup1Item, iType, iHandle, iRect);  
  363.         SetDialogItem(theDialog, popup1Item, userItem, Handle(NewUserItemProc(@UpdatePopUp)), iRect);
  364.         
  365.         theGlobals.menus[smallPopupID].hMenu := GetMenu(smallPopupID);
  366.         InsertMenu(theGlobals.menus[smallPopupID].hMenu, -1);
  367.         CalcMenuSize(theGlobals.menus[smallPopupID].hMenu);
  368.         theGlobals.menus[smallPopupID].selectedItem := 1;
  369.         theGlobals.menus[smallPopupID].smallFont := TRUE;
  370.         GetDialogItem(theDialog, popup2Item, iType, iHandle, iRect);
  371.         SetDialogItem(theDialog, popup2Item, userItem, Handle(NewUserItemProc(@UpdatePopUp)), iRect);
  372.  
  373.         GetDialogItem(theDialog, defaultItem, iType, iHandle, iRect); 
  374.         SetDialogItem(theDialog, defaultItem, userItem, Handle(NewUserItemProc(@DrawDefaultBtn)), iRect);
  375.  
  376.         ShowWindow(theDialog);
  377.         HandleEvents(theDialog);
  378.  
  379.         DeleteMenu(normalPopupID);
  380.         DeleteMenu(smallPopupID);
  381.         DisposeDialog(theDialog);
  382.     END;
  383.  
  384. END.
  385.